package struts.action;

import global.GlobalConstants;

import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.SystemUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ExceptionHandler;
import org.apache.struts.config.ExceptionConfig;

import bean.ResultMessageObject;

/**
 * @author ben
 * 
 */
public class CustomExceptionHandler extends ExceptionHandler {
	private static final Log log = LogFactory.getLog(CustomExceptionHandler.class);

	@Override
	public ActionForward execute(Exception ex, ExceptionConfig ae, ActionMapping mapping, ActionForm formInstance,
			HttpServletRequest request, HttpServletResponse response) throws ServletException {

		ResultMessageObject result = new ResultMessageObject();
		result.setFunctionId(StringUtils.removeStart(mapping.getPath().toUpperCase(), "/"));

		// if business error occurs, only set error message.
		if (ex instanceof IllegalPageOperationException) {
			result.setTitleCode("Z3101W0003");
			result.setCode("Z3101W0103");
			result.setSyserror(false);
		}
		// if system error occurs, set error message and dump the message into log.
		else {
			result.setTitleCode("Z3101W0001");
			result.setCode("Z3101W0101");
			result.setSyserror(true);
			result.setError(ex);
			dumpError(ex, mapping, formInstance, request, response);
		}

		request.getSession().setAttribute(ResultMessageObject.RESULT_MESSAGE_KEY, result);

		// In Ajax request cases, set the status of '500' to represent error condition.
		response.setStatus(GlobalConstants.AJAX_RESPONSE_ERROR_STATUS);
		return mapping.findForward("syserror");
	}

	/**
	 * 错误发生时的错误日志生成
	 * 
	 * @param ex
	 * @param mapping
	 * @param formInstance
	 * @param request
	 * @param response
	 */
	@SuppressWarnings("unchecked")
	private void dumpError(Exception ex, ActionMapping mapping, ActionForm formInstance, HttpServletRequest request,
			HttpServletResponse response) {
		try {

			StringBuilder sb = new StringBuilder();

			sb.append(
					"[错误信息开始]====================================================================================================================")
					.append(SystemUtils.LINE_SEPARATOR);

			sb.append("[Exception]").append(SystemUtils.LINE_SEPARATOR);
			for (Throwable t : ExceptionUtils.getThrowables(ex)) {
				sb.append(ExceptionUtils.getFullStackTrace(t)).append(SystemUtils.LINE_SEPARATOR);
			}
			sb.append("[ActionMapping]").append(SystemUtils.LINE_SEPARATOR);
			sb.append(ToStringBuilder.reflectionToString(mapping, ToStringStyle.MULTI_LINE_STYLE)).append(SystemUtils.LINE_SEPARATOR);
			sb.append("[ActionForm]").append(SystemUtils.LINE_SEPARATOR);
			sb.append(ToStringBuilder.reflectionToString(formInstance, ToStringStyle.MULTI_LINE_STYLE)).append(SystemUtils.LINE_SEPARATOR);
			sb.append("[HttpSession]").append(SystemUtils.LINE_SEPARATOR);
			HttpSession session = request.getSession(false);
			Enumeration<String> names;

			if (session == null) {
				sb.append("  session invalid !!").append(SystemUtils.LINE_SEPARATOR);
			} else {
				names = session.getAttributeNames();
				while (names.hasMoreElements()) {
					String name = names.nextElement();
					String value = (session.getAttribute(name) instanceof String ? (String) session.getAttribute(name) : ToStringBuilder
							.reflectionToString(session.getAttribute(name)));
					sb.append("  " + name + " = " + value).append(SystemUtils.LINE_SEPARATOR);
				}
			}
			sb.append("[HTTP Request]").append(SystemUtils.LINE_SEPARATOR);
			sb.append("  RemoteAddr:" + request.getRemoteAddr()).append(SystemUtils.LINE_SEPARATOR);
			sb.append("  RequestURL:" + request.getRequestURL().toString()).append(SystemUtils.LINE_SEPARATOR);
			sb.append("  QueryStrings:" + request.getQueryString()).append(SystemUtils.LINE_SEPARATOR);
			sb.append("  RequestedSessionId:" + request.getRequestedSessionId()).append(SystemUtils.LINE_SEPARATOR);
			sb.append("  RequestedSessionIdValid:" + request.isRequestedSessionIdValid()).append(SystemUtils.LINE_SEPARATOR);

			sb.append("[HTTP Request Attributes]").append(SystemUtils.LINE_SEPARATOR);
			names = request.getAttributeNames();

			while (names.hasMoreElements()) {

				String name = names.nextElement();
				sb.append("  " + name + " = " + request.getAttribute(name)).append(SystemUtils.LINE_SEPARATOR);
			}

			sb.append("[HTTP Request Parameters]").append(SystemUtils.LINE_SEPARATOR);
			names = request.getParameterNames();

			while (names.hasMoreElements()) {

				String name = names.nextElement();
				sb.append("  " + name + " = " + request.getParameter(name)).append(SystemUtils.LINE_SEPARATOR);
			}

			sb.append("[HTTP Headers]").append(SystemUtils.LINE_SEPARATOR);
			names = request.getHeaderNames();

			while (names.hasMoreElements()) {

				String name = names.nextElement();
				sb.append("  " + name + " = " + request.getHeader(name)).append(SystemUtils.LINE_SEPARATOR);
			}

			sb.append(
					"[错误信息结束]======================================================================================================================")
					.append(SystemUtils.LINE_SEPARATOR);

			log.error(sb.toString());

		} catch (Exception e) {
			log.warn("打包错误信息时出错", e);
		}
	}

}
